import './ViewerMain.css';

import { useEffect, useState } from 'react';
import { redux } from '@ohif/core';
import { ConnectedViewportGrid } from '../ViewportGrid';
import { useAppContext } from '../../context/AppContext';
import PropTypes from 'prop-types';
import React from 'react';
import memoize from 'lodash/memoize';
import _values from 'lodash/values';
import { useDispatch, useSelector } from 'react-redux';

var values = memoize(_values);

const {
  setViewportSpecificData: setViewportSpecificDataAction,
  clearViewportSpecificData: clearViewportSpecificDataAction,
  setLayout: setLayoutAction,
  setViewportMaximized: setViewportMaximizedAction,
} = redux.actions;

const _getDisplaySets = studies => {
  const displaySets = [];
  studies.forEach(study => {
    study.displaySets.forEach(dSet => {
      if (!dSet.plugin) {
        dSet.plugin = 'cornerstone';
      }
      displaySets.push(dSet);
    });
  });

  return displaySets;
};

const _findDisplaySet = (studies, StudyInstanceUID, displaySetInstanceUID) => {
  const study = studies.find(study => {
    return study.StudyInstanceUID === StudyInstanceUID;
  });

  if (!study) {
    return;
  }

  return study.displaySets.find(displaySet => {
    return displaySet.displaySetInstanceUID === displaySetInstanceUID;
  });
}

let initLayout = false;

const ViewerMain = ({ studies, isStudyLoaded }) => {
  const [displaySets, setDisplaySets] = useState([]);

  const { appConfig } = useAppContext();
  const { layout, viewportSpecificData } = useSelector(state => {
    const modeState = state.viewports[state.viewports.viewMode];
    const { layout, viewportSpecificData } = modeState;
    return { layout, viewportSpecificData };
  });

  const dispatch = useDispatch();
  const setViewportSpecificData = (viewportIndex, data) => dispatch(setViewportSpecificDataAction(viewportIndex, data));
  // const clearViewportSpecificData = () => dispatch(clearViewportSpecificDataAction());
  const setLayout = layout => dispatch(setLayoutAction(layout));
  const setViewportMaximized = viewportIndex => dispatch(setViewportMaximizedAction(viewportIndex));

  useEffect(() => {
    setDisplaySets(_getDisplaySets(studies));
  }, [studies]);

  useEffect(() => {
    // vtk viewports
    if (layout.viewports.some(vp => vp.plugin === 'vtk-mpr')) return;

    const { isMobile } = appConfig;
    if (!initLayout && displaySets.length > 0) {
      // auto layout
      let numRows = 1, numColumns = 1;
      if (displaySets.length > 2) {
        numRows++;
        numColumns++;
      } else if (displaySets.length > 1) {
        numColumns++;
      }
      const numViewports = numRows * numColumns;
      const viewports = [];
      for (let i = 0; i < numViewports; ++i) {
        viewports.push({ plugin: 'cornerstone' });
      }
      setLayout({ numRows, numColumns, viewports });
      if (isMobile) {
        setViewportMaximized(0);
      }
      initLayout = true;
    }

    fillEmptyViewportPanes();

    // return () => {
    //   Object.keys(viewportSpecificData).forEach(viewportIndex => {
    //     clearViewportSpecificData(viewportIndex);
    //   });

    //   // TODO: These don't have to be viewer specific?
    //   // Could qualify for other routes?
    //   // hotkeys.destroy();

    //   // Remove beforeUnload event handler...
    //   //window.removeEventListener('beforeunload', unloadHandlers.beforeUnload);
    //   // Destroy the synchronizer used to update reference lines
    //   //OHIF.viewer.updateImageSynchronizer.destroy();
    //   // TODO: Instruct all plugins to clean up themselves
    //   //
    //   // Clear references to all stacks in the StackManager
    //   //StackManager.clearStacks();
    //   // @TypeSafeStudies
    //   // Clears OHIF.viewer.Studies collection
    //   //OHIF.viewer.Studies.removeAll();
    //   // @TypeSafeStudies
    //   // Clears OHIF.viewer.StudyMetadataList collection
    //   //OHIF.viewer.StudyMetadataList.removeAll();
    // }
  }, [displaySets, layout]);

  const fillEmptyViewportPanes = () => {
    // TODO: Here is the entry point for filling viewports on load.
    const dirtyViewportPanes = [];

    if (!displaySets || !displaySets.length) {
      return;
    }

    for (let i = 0; i < layout.viewports.length; i++) {
      const viewportPane = viewportSpecificData[i];
      const isNonEmptyViewport =
        viewportPane &&
        viewportPane.StudyInstanceUID &&
        viewportPane.displaySetInstanceUID;

      if (isNonEmptyViewport) {
        dirtyViewportPanes.push({
          empty: false,
          StudyInstanceUID: viewportPane.StudyInstanceUID,
          displaySetInstanceUID: viewportPane.displaySetInstanceUID,
        });

        continue;
      }

      const foundDisplaySet =
        displaySets.find(
          ds =>
            !dirtyViewportPanes.some(
              v => v.displaySetInstanceUID === ds.displaySetInstanceUID
            )
        ) || {};

      dirtyViewportPanes.push({ ...foundDisplaySet, empty: true });
    }

    dirtyViewportPanes.forEach((vp, i) => {
      if (vp && vp.StudyInstanceUID && vp.empty) {
        setViewportData({
          viewportIndex: i,
          StudyInstanceUID: vp.StudyInstanceUID,
          displaySetInstanceUID: vp.displaySetInstanceUID,
        });
      }
    });
  };

  const setViewportData = ({
    viewportIndex,
    StudyInstanceUID,
    displaySetInstanceUID,
  }) => {
    let displaySet = _findDisplaySet(
      studies,
      StudyInstanceUID,
      displaySetInstanceUID
    );

    if (displaySet && displaySet.isDerived) {
      const { Modality } = displaySet;
      displaySet = displaySet.getSourceDisplaySet(studies);

      if (!displaySet) {
        throw new Error(
          `Referenced series for ${Modality} dataset not present.`
        );
      }
    }

    setViewportSpecificData(viewportIndex, displaySet);
  };

  const viewportData = values(viewportSpecificData);
  return (
    <div className="viewer-main">
      {displaySets.length > 0 && (
        <ConnectedViewportGrid
          isStudyLoaded={isStudyLoaded}
          studies={studies}
          viewportData={viewportData}
          setViewportData={setViewportData}
        >
          {/* Children to add to each viewport that support children */}
        </ConnectedViewportGrid>
      )}
    </div>
  );
}

ViewerMain.propTypes = {
  studies: PropTypes.array,
  isStudyLoaded: PropTypes.bool,
};

export default ViewerMain;
